#include "stdafx.h"

#include "SortSegment.h"


CSortSegment::CSortSegment(const ZMVector<ZMPoint3D>&poly)
{
	InitTree(poly);
}


CSortSegment::~CSortSegment()
{
}

void CSortSegment::InitTree(const ZMVector<ZMPoint3D>& poly)
{
	vector<Point> vPnt3, vPnt2;
	m_vSegment2.clear();
	m_vSegment3.clear();
	for (int i = 0; i < poly.size(); ++i)
	{
		ZMPoint3D pnt = poly[i];
		Point pnt3 = Point(pnt[0], pnt[1], pnt[2]); pnt3.Index() = i;
		Point pnt2 = Point(pnt[0], pnt[1], 0); pnt2.Index() = i;
		vPnt3.push_back(pnt3);
		vPnt2.push_back(pnt2);
	}

	for (int i = 0; i < (int)vPnt3.size() - 1; ++i)
	{
		m_vSegment3.push_back(Segment(vPnt3[i], vPnt3[i + 1]));
		m_vSegment2.push_back(Segment(vPnt2[i], vPnt2[i + 1]));
	}
	m_pTree2 = shared_ptr<Tree>(new Tree(m_vSegment2.begin(), m_vSegment2.end()));
	m_pTree3 = shared_ptr<Tree>(new Tree(m_vSegment3.begin(), m_vSegment3.end()));
	m_pTree2->accelerate_distance_queries();
	m_pTree3->accelerate_distance_queries();
}

ZMPoint3D CSortSegment::ClosePoint(const ZMPoint3D& pnt, int& iPntIndex, ZMPoint3D::euDisType disType)  const
{
	ZMPoint3D ret;
	Point_and_primitive_id prim;
	if (disType == ZMPoint3D::TYPE_3D)
	{
		prim = m_pTree3->closest_point_and_primitive(Point(pnt[0], pnt[1], pnt[2]));
		iPntIndex = (prim.second - m_vSegment3.begin());
	}
	else if (disType == ZMPoint3D::TYPE_2D)
	{
		prim = m_pTree2->closest_point_and_primitive(Point(pnt[0], pnt[1], 0));
		iPntIndex = (prim.second - m_vSegment2.begin());
	}

	Point pntCloest = prim.first;
	ret = ZMPoint3D((ZMReal)pntCloest[0], (ZMReal)pntCloest[1], (ZMReal)pntCloest[2]);
	return ret;
}

int CSortSegment::GetAllIntersection(const ZMPoint3D& pntFrom, const ZMPoint3D& pntTo, ZMVector<int>& iSegIndex, ZMVector<euIntersectionType>& vIntersectionType, ZMVector<ZMPoint3D> &vPntIntersection, ZMPoint3D::euDisType disType)  const
{
	int iRet = 0;
	Segment seg_query;
	std::list<Segment_intersection> lsSegInter;
	if (disType == ZMPoint3D::TYPE_3D)
	{
		seg_query = Segment(Point(pntFrom[0], pntFrom[1], pntFrom[2]), Point(pntTo[0], pntTo[1], pntTo[2]));
		m_pTree3->all_intersections(seg_query, std::back_inserter(lsSegInter));
	}
	else if (disType == ZMPoint3D::TYPE_2D)
	{
		seg_query = Segment(Point(pntFrom[0], pntFrom[1], 0), Point(pntTo[0], pntTo[1], 0));
		m_pTree2->all_intersections(seg_query, std::back_inserter(lsSegInter));
	}
	for (Segment_intersection& segInter : lsSegInter)
	{
		if (boost::get<Point>(&(segInter->first)))
		{
			Point pnt = *(boost::get<Point>(&(segInter->first)));
			vIntersectionType.push_back(TYPE_ONE_POINT);
			vPntIntersection.push_back(ZMPoint3D((ZMReal)pnt[0], (ZMReal)pnt[1], (ZMReal)pnt[2]));
			++iRet;
		}
		else if (boost::get<Segment>(&(segInter->first)))
		{
			Point pnt0 = (*(boost::get<Segment>(&(segInter->first))))[0];
			Point pnt1 = (*(boost::get<Segment>(&(segInter->first))))[1];
			vIntersectionType.push_back(TYPE_SAME);
			vPntIntersection.push_back(ZMPoint3D((ZMReal)pnt0[0], (ZMReal)pnt0[1], (ZMReal)pnt0[2]));
			vPntIntersection.push_back(ZMPoint3D((ZMReal)pnt1[0], (ZMReal)pnt1[1], (ZMReal)pnt1[2]));
			iRet+=2;
		}
		if (disType == ZMPoint3D::TYPE_3D)
		{
			iSegIndex.push_back(segInter->second - m_vSegment3.begin());
		}
		if (disType == ZMPoint3D::TYPE_2D)
		{
			iSegIndex.push_back(segInter->second - m_vSegment2.begin());
		}
	}
	return iRet;
}
